package jvm.quote;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.util.concurrent.TimeUnit;
/**
 * @author cyt
 * @create 2020-09-11 18:15
 */
public class Empty {
    public static Empty empty;
    public static PhantomReference<Empty> reference;
    public static ReferenceQueue<Empty> queue;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("调用 finalize");
        empty = this;
    }

    public static class Check extends Thread {
        @Override
        public void run() {
            while (true) {
                super.run();
                if (reference != null) {
                    PhantomReference<Empty> test = null;
                    try {
                        test = (PhantomReference<Empty>) queue.remove();
                    } catch (Exception e) {

                    }
                    if (test != null) {
                        System.out.println("跟踪垃圾回收过程， Empty 被GC");
                    }
                }
            }
        }
    }

    /**
     * 形同虚设的一个引用类型， 当试图从虚引用中获得对象的时候
     * 它总是空的 ！ 为一个对象设置虚引用关联的唯一目的是跟踪垃圾回收的过程
     * 比如: 能在这个对象被回收的时候发出一个通知
     */
    public static void main(String[] args) {
        Check check = new Check();
        check.setDaemon(true);
        check.start();

        queue = new ReferenceQueue<>();
        empty = new Empty();
        reference = new PhantomReference<>(empty, queue);
        // 取消强引用
        empty = null;
        System.out.println(reference.get());

        System.out.println("第一次GC");
        // 把回收的对象， 放到引用队列中
        System.gc();
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("after 第一次GC");
        if (empty != null) {
            System.out.println("empty 可用");
        } else {
            System.out.println("empty 不可用");
        }
        System.out.println("第二次GC");

        // 取消强引用
        empty = null;
        System.gc();

        System.out.println("after 第二次GC");
        if (empty != null) {
            System.out.println("empty 可用");
        } else {
            System.out.println("empty 不可用");
        }
    }
}

